}
#endif /* OSTREE_DISABLE_GPGME */
+static gboolean
+get_signapi_remote_option (OstreeRepo *repo,
+ OstreeSign *sign,
+ const char *remote_name,
+ const char *keysuffix,
+ char **out_value,
+ GError **error)
+{
+ g_autofree char *key = g_strdup_printf ("verification-%s-%s", ostree_sign_get_name (sign), keysuffix);
+ return ostree_repo_get_remote_option (repo, remote_name, key, NULL, out_value, error);
+}
+
/* _load_public_keys:
*
* Load public keys according remote's configuration:
- * inlined key passed via config option `verification-key` or
- * file name with public keys via `verification-file` option.
+ * inlined key passed via config option `verification-<signapi>-key` or
+ * file name with public keys via `verification-<signapi>-file` option.
*
* If both options are set then load all all public keys
* both from file and inlined in config.
gboolean loaded_from_file = TRUE;
gboolean loaded_inlined = TRUE;
- ostree_repo_get_remote_option (repo,
- remote_name,
- "verification-file", NULL,
- &pk_file, NULL);
-
- ostree_repo_get_remote_option (repo,
- remote_name,
- "verification-key", NULL,
- &pk_ascii, NULL);
+ if (!get_signapi_remote_option (repo, sign, remote_name, "file", &pk_file, error))
+ return FALSE;
+ if (!get_signapi_remote_option (repo, sign, remote_name, "key", &pk_ascii, error))
+ return FALSE;
/* return TRUE if there is no configuration for remote */
if ((pk_file == NULL) &&(pk_ascii == NULL))
{
/* list all signature types in detached metadata and check if signed by any? */
g_auto (GStrv) names = ostree_sign_list_names();
- g_autoptr (GError) verification_error = NULL;
-
- glnx_throw (&verification_error, "signed with unknown key");
+ guint n_invalid_signatures = 0;
+ guint n_unknown_signatures = 0;
+ g_autoptr (GError) last_sig_error = NULL;
+ gboolean found_sig = FALSE;
for (char **iter=names; iter && *iter; iter++)
{
g_autoptr (GVariant) signatures = NULL;
const gchar *signature_key = NULL;
GVariantType *signature_format = NULL;
- g_autoptr (GError) local_error = NULL;
- if ((sign = ostree_sign_get_by_name (*iter, &local_error)) == NULL)
- continue;
+ if ((sign = ostree_sign_get_by_name (*iter, NULL)) == NULL)
+ {
+ n_unknown_signatures++;
+ continue;
+ }
signature_key = ostree_sign_metadata_key (sign);
signature_format = (GVariantType *) ostree_sign_metadata_format (sign);
continue;
/* Try to load public key(s) according remote's configuration */
- if (_load_public_keys (sign, repo, remote_name, &local_error))
+ if (!_load_public_keys (sign, repo, remote_name, error))
+ return FALSE;
+
+ found_sig = TRUE;
+
+ /* Return true if any signature fit to pre-loaded public keys.
+ * If no keys configured -- then system configuration will be used */
+ if (!ostree_sign_data_verify (sign,
+ signed_data,
+ signatures,
+ last_sig_error ? NULL : &last_sig_error))
{
- /* Return true if any signature fit to pre-loaded public keys.
- * If no keys configured -- then system configuration will be used */
- if (ostree_sign_data_verify (sign,
- signed_data,
- signatures,
- &local_error))
- return TRUE;
+ n_invalid_signatures++;
+ continue;
}
+ /* Accept the first valid signature */
+ return TRUE;
+ }
- /* Save error message for better reason detection later if needed */
- glnx_prefix_error (&verification_error, "%s", local_error->message);
+ if (!found_sig)
+ {
+ if (n_unknown_signatures > 0)
+ return glnx_throw (error, "No signatures found (%d unknown type)", n_unknown_signatures);
+ return glnx_throw (error, "No signatures found");
}
- /* In case if there were no signatures of known type
- * or metadata contains invalid data */
- return glnx_throw (error, "%s", verification_error->message);
+ g_assert (last_sig_error);
+ g_propagate_error (error, g_steal_pointer (&last_sig_error));
+ if (n_invalid_signatures > 1)
+ glnx_prefix_error (error, "(%d other invalid signatures)", n_invalid_signatures-1);
+ return FALSE;
}
static gboolean
if (pull_data->sign_verify &&
!g_hash_table_contains (pull_data->verified_commits, checksum))
{
- gboolean ret = FALSE;
- g_autoptr (GError) verification_error = NULL;
+ g_autoptr(GError) last_verification_error = NULL;
+ gboolean found_any_signature = FALSE;
+ gboolean found_valid_signature = FALSE;
/* list all signature types in detached metadata and check if signed by any? */
g_auto (GStrv) names = ostree_sign_list_names();
- for (char **iter=names; !ret && iter && *iter; iter++)
+ for (char **iter=names; iter && *iter; iter++)
{
g_autoptr (OstreeSign) sign = NULL;
- g_autoptr (GError) local_error = NULL;
- if ((sign = ostree_sign_get_by_name (*iter, &local_error)) == NULL)
+ if ((sign = ostree_sign_get_by_name (*iter, NULL)) == NULL)
continue;
/* Try to load public key(s) according remote's configuration */
- if (_load_public_keys (sign, pull_data->repo, pull_data->remote_name, &local_error))
- {
+ if (!_load_public_keys (sign, pull_data->repo, pull_data->remote_name, error))
+ return FALSE;
- /* Set return to true if any sign fit */
- if (ostree_sign_commit_verify (sign,
- pull_data->repo,
- checksum,
- cancellable,
- &local_error))
- ret = TRUE;
- }
+ found_any_signature = TRUE;
- /* Save error message for better reason detection later if needed */
- if (!ret)
- glnx_prefix_error (&verification_error, "%s", local_error->message);
+ /* Set return to true if any sign fit */
+ if (ostree_sign_commit_verify (sign,
+ pull_data->repo,
+ checksum,
+ cancellable,
+ last_verification_error ? NULL : &last_verification_error))
+ {
+ found_valid_signature = TRUE;
+ break;
+ }
}
- if (!ret)
- return glnx_throw (error, "Can't verify commit %s: %s", checksum, verification_error->message);
+ if (!found_any_signature)
+ return glnx_throw (error, "No signatures found for commit %s", checksum);
+
+ if (!found_valid_signature)
+ {
+ g_assert (last_verification_error);
+ g_propagate_error (error, g_steal_pointer (&last_verification_error));
+ return glnx_prefix_error (error, "Can't verify commit %s", checksum);
+ }
}
/* If we found a legacy transaction flag, assume we have to scan.
${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u ${COMMIT_SIGN}
cd ${test_tmpdir}
- repo_reinit --set=verification-key=${PUBLIC_KEY}
+ repo_reinit --set=verification-${engine}-key=${PUBLIC_KEY}
${OSTREE} --repo=repo pull origin main
assert_has_file repo/tmp/cache/summaries/origin
assert_has_file repo/tmp/cache/summaries/origin.sig
echo "ok ${engine} prune summary cache"
cd ${test_tmpdir}
- repo_reinit --set=verification-key=${PUBLIC_KEY}
+ repo_reinit --set=verification-${engine}-key=${PUBLIC_KEY}
mkdir cachedir
${OSTREE} --repo=repo pull --cache-dir=cachedir origin main
assert_not_has_file repo/tmp/cache/summaries/origin
echo "ok ${engine} pull with signed summary and cachedir"
cd ${test_tmpdir}
- repo_reinit --set=verification-key=${PUBLIC_KEY}
+ repo_reinit --set=verification-${engine}-key=${PUBLIC_KEY}
mv ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{,.good}
echo invalid > ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig
if ${OSTREE} --repo=repo pull origin main 2>err.txt; then
assert_not_reached "Successful pull with invalid ${engine} signature"
fi
- assert_file_has_content err.txt "signed with unknown key"
+ assert_file_has_content err.txt "No signatures found"
mv ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.good,}
echo "ok ${engine} pull with invalid ${engine} summary signature fails"
${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u ${COMMIT_SIGN}
cd ${test_tmpdir}
- repo_reinit --set=verification-key=${PUBLIC_KEY}
+ repo_reinit --set=verification-${engine}-key=${PUBLIC_KEY}
${OSTREE} --repo=repo pull origin main
echo "ok ${engine} pull delta with signed summary"
# Reset to the old valid summary and pull to cache it
cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.1,}
cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.1,}
-repo_reinit --set=verification-key=${PUBLIC_KEY}
+repo_reinit --set=verification-ed25519-key=${PUBLIC_KEY}
${OSTREE} --repo=repo pull origin main
assert_has_file repo/tmp/cache/summaries/origin
assert_has_file repo/tmp/cache/summaries/origin.sig
if ${OSTREE} --repo=repo pull origin main 2>err.txt; then
assert_not_reached "Successful pull with old summary"
fi
-assert_file_has_content err.txt "signed with unknown key"
+assert_file_has_content err.txt "no valid ed25519 signatures found"
assert_has_file repo/tmp/cache/summaries/origin
assert_has_file repo/tmp/cache/summaries/origin.sig
cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary.1 >&2
# Reset to the old valid summary and pull to cache it
cp ${test_tmpdir}/ostree-srv/gnomerepo/summary{.1,}
cp ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig{.1,}
-repo_reinit --set=verification-key=${PUBLIC_KEY}
+repo_reinit --set=verification-ed25519-key=${PUBLIC_KEY}
${OSTREE} --repo=repo pull origin main
assert_has_file repo/tmp/cache/summaries/origin
assert_has_file repo/tmp/cache/summaries/origin.sig
fi
echo "ok pull failure without keys preloaded"
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-key "somewrongkey"
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-dummy-key "somewrongkey"
if ${CMD_PREFIX} ostree --repo=repo pull origin main; then
assert_not_reached "pull with unknown key unexpectedly succeeded"
fi
echo "ok pull failure with incorrect key option"
-${CMD_PREFIX} ostree --repo=repo config unset 'remote "origin"'.verification-key
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-file "/non/existing/file"
+${CMD_PREFIX} ostree --repo=repo config unset 'remote "origin"'.verification-dummy-key
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-dummy-file "/non/existing/file"
if ${CMD_PREFIX} ostree --repo=repo pull origin main; then
assert_not_reached "pull with unknown keys file unexpectedly succeeded"
fi
echo "ok pull failure with incorrect keys file option"
# Test with correct dummy key
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-key "${DUMMYSIGN}"
-${CMD_PREFIX} ostree --repo=repo config unset 'remote "origin"'.verification-file
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-dummy-key "${DUMMYSIGN}"
+${CMD_PREFIX} ostree --repo=repo config unset 'remote "origin"'.verification-dummy-file
test_signed_pull "dummy" ""
if ! has_libsodium; then
COMMIT_ARGS="--sign=${SECRET} --sign-type=ed25519"
repo_init --set=sign-verify=true
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-key "${PUBLIC}"
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-ed25519-key "${PUBLIC}"
test_signed_pull "ed25519" "key"
# Prepare files with public ed25519 signatures
done > ${PUBKEYS}
# Test case with the file containing incorrect signatures and with the correct key set
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-file "${PUBKEYS}"
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-ed25519-file "${PUBKEYS}"
test_signed_pull "ed25519" "key+file"
# Add correct key into the list
echo ${PUBLIC} >> ${PUBKEYS}
repo_init --set=sign-verify=true
-${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-file "${PUBKEYS}"
+${CMD_PREFIX} ostree --repo=repo config set 'remote "origin"'.verification-ed25519-file "${PUBKEYS}"
test_signed_pull "ed25519" "file"